/**
 * 测试对象的特性和函数
 */

let oldObj = { a: 100 };
var freezeOb = Object.freeze(oldObj);
console.log(oldObj == freezeOb);
console.log(freezeOb.a);//100
freezeOb.b = 20;
console.log(freezeOb.b); // 显示undefined，不能被赋值，但是不会报错
freezeOb.a = 25;
console.log(freezeOb.a);//仍然为100
oldObj.a = 25;
console.log(oldObj.a);//不可以被编辑

let a = 100;
let b = "hello";
let c = () => {
    return 255.31;
}
let simpleObject = {
    a, b, c,
    ['this' + 'IsA' + 'Func']: function () {
        return "112233";
    }
}
console.log(simpleObject.c()); // 255.31
simpleObject['my' + 'properties'] = 44.234;
console.log(simpleObject.myproperties);
simpleObject.thisIsAFunc();

/**
 * isFinite() 函数用于检查其参数是否是无穷大，也可以理解为是否为一个有限数值（finite number）。
 * 提示： 如果参数是 NaN，正无穷大或者负无穷大，会返回 false，其他返回 true。
 */

let tPara = NaN;
console.log(isFinite(tPara));// false
tPara = 10;
console.log(isFinite(tPara));// false

/**
 * 原生JSON对象支持
 */

let jsonOb = JSON.parse("{\"val\":100, \"innerob\":{\"b\":35}}");
console.log("jsonOb.val=", jsonOb.val);

/**
 * JSON.stringify(value[, replacer[, space]])
 * value:
 * 必需， 要转换的 JavaScript 值（通常为对象或数组）。
 * replacer:
 * 可选。用于转换结果的函数或数组。
 * 如果 replacer 为函数，则 JSON.stringify 将调用该函数，并传入每个成员的键和值。使用返回值而不是原始值。如果此函数返回 undefined，则排除成员。根对象的键是一个空字符串：""。
 * 如果 replacer 是一个数组，则仅转换该数组中具有键值的成员。成员的转换顺序与键在数组中的顺序一样。
 * space:
 * 可选，文本添加缩进、空格和换行符，如果 space 是一个数字，则返回值文本在每个级别缩进指定数目的空格，如果 space 大于 10，则文本缩进 10 个空格。space 也可以使用非数字，如：\t。
 */
let jsonStr = JSON.stringify(jsonOb, (k, v) => {
    console.log("key=%s,value=%s", k, v);
    return v;
});
console.log("jsonStr=", jsonStr);


/**
 * splice() 方法向/从数组中添加/删除项目，然后返回被删除的项目。
 * 该方法会改变原始数组。
 * arrayObject.splice(index,howmany,item1,.....,itemX)
 * index:必需。整数，规定添加/删除项目的位置，使用负数可从数组结尾处规定位置。
 * howmany:必需。要删除的项目数量。如果设置为 0，则不会删除项目。
 * item1, ..., itemX:可选。向数组添加的新项目。
 * splice() 方法可删除从 index 处开始的零个或多个元素，并且用参数列表中声明的一个或多个值来替换那些被删除的元素。
 * 如果从 arrayObject 中删除了元素，则返回的是含有被删除的元素的数组。
 */
let tmpArr = [0, 1, 2, 3, 4, 5];
let newArr = tmpArr.splice(2, 1);
console.log(tmpArr); // [ 0, 1, 3, 4, 5 ]
console.log(newArr); // [ 2 ]

/**
 * vue源代码中充斥着各种通过反射来调用方法的做法，这种做法是因为js对于某些函数没有保护
 * 用户代码可以覆盖原来的定义，所以需要通过反射的方式，比如：hasOwnProperty
 * 
 * var foo = {
 *     hasOwnProperty: function() {
 *         return false;
 *     },
 *     bar: 'Here be dragons'
 * };
 * 
 * foo.hasOwnProperty('bar'); // 始终返回 false
 * 
 * // 如果担心这种情况，可以直接使用原型链上真正的 hasOwnProperty 方法
 * // 使用另一个对象的`hasOwnProperty` 并且call
 * ({}).hasOwnProperty.call(foo, 'bar'); // true
 * 
 * // 也可以使用 Object 原型上的 hasOwnProperty 属性
 * Object.prototype.hasOwnProperty.call(foo, 'bar'); // true
 */

/**
 * 对象的继承，使用Object.create()方法
 */

let parentOb = { a: 100 };
let childOb = Object.create(parentOb, {
    bar: {
        configurable: false,
        get: function () { return bar; },
        set: function (value) { bar = 33 }
    }
});

console.log(childOb.a); //100
childOb.bar = 122;
console.log(childOb.bar);//33

var onlyReadObj = ({
    a: 221,
    b: 20
});

console.log(onlyReadObj.a);
onlyReadObj.a = 22;
console.log(onlyReadObj.a);